/*
* Copyright (c) 2014 Qunar.com. All Rights Reserved.
*/
package net.oschina.bilbodai.common.beanutil.property.asm.lexer.code;

import net.oschina.bilbodai.common.beanutil.property.asm.lexer.parse.TokenApplyCtx;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;

import static org.objectweb.asm.Opcodes.CHECKCAST;
import static org.objectweb.asm.Opcodes.DUP;
import static org.objectweb.asm.Opcodes.IFNULL;

/**
 * @author qt-maodai  Date: 15-8-7 Time: 上午11:47
 * @version $Id$
 */
public abstract class BaseCodeApplier implements ICodeApplier {
    private final CodeApply codeApply;

    public BaseCodeApplier(CodeApply codeApply) {
        this.codeApply = codeApply;
    }

    //属性所在的实例的类型,比如 Person{ String name} 中 propertyName=name,instanceType=Person
    public CodeApplyResult apply(MethodVisitor mv, TokenApplyCtx applyCtx) throws Exception {
        mv.visitInsn(DUP);
        mv.visitJumpInsn(IFNULL, applyCtx.getRetNullLabel());
        typeCheck(mv, codeApply);
        return applyCode(mv, codeApply);
    }

    private void typeCheck(MethodVisitor mv, CodeApply codeApply) {
        if (!codeApply.getParentType().equals(codeApply.getStackType())) {
            mv.visitTypeInsn(CHECKCAST, Type.getInternalName(codeApply.getParentType()));
        }
        //        if (Object.class.equals(codeApply.getParentType())) {
        //            if (!Object.class.equals(codeApply.getThisType())) {
        //                mv.visitTypeInsn(CHECKCAST, Type.getInternalName(codeApply.getThisType()));
        //            }
        //        } else {
        //            if (!inputClassType.isAssignableFrom(getInstanceType())) {
        //                mv.visitTypeInsn(CHECKCAST, Type.getInternalName(getInstanceType()));
        //            }
        //        }
    }

    protected abstract CodeApplyResult applyCode(MethodVisitor mv, CodeApply codeApply) throws Exception;

}